import { v4 as uuid } from 'uuid'
import tinymce from 'tinymce/tinymce'
import { StdAnnexV2 } from './annex'
import { StdPage } from './page'
import { StdDoc } from './doc'
import { contentTypes, allContentTypes, isAnnexByType } from '@/constants/structure'
import { headTypes, tailTypes, contentPrototypes } from '@/constants/structure'
import store from '@/store'
import { parsePageData } from './parse'
import { getPageByBlockId } from '../helpers'

/** 为节点添加 dataIndex */
export function getSortedBlockList(arr) {
  let item1Index = 1,
    item2Index = 1,
    item3Index = 1,
    item4Index = 1,
    dataIndex = 0,
    lastIndex = 0,
    currentItem1Index = '',
    currentItem2Index = '',
    currentItem3Index = '',
    currentItem4Index = ''
  return arr.map((i) => {
    if (contentTypes.includes(i.dataType)) {
      const idx = ++dataIndex
      lastIndex = idx
      item1Index = 1
      return { ...i, dataIndex: idx }
    }
    if (i.dataType === 'paragraph') {
      return { ...i, dataIndex: lastIndex }
    }
    if (i.dataType === 'item1') {
      ;(item2Index = 1), (item3Index = 1), (item4Index = 1)
      currentItem1Index = dataIndex + '.' + item1Index++
      lastIndex = currentItem1Index
      return { ...i, dataIndex: currentItem1Index }
    }
    if (i.dataType === 'item2') {
      ;(item3Index = 1), (item4Index = 1)
      currentItem2Index = currentItem1Index + '.' + item2Index++
      lastIndex = currentItem2Index
      return { ...i, dataIndex: currentItem2Index }
    }
    if (i.dataType === 'item3') {
      currentItem3Index = currentItem2Index + '.' + item3Index++
      item4Index = 1
      lastIndex = currentItem3Index
      return { ...i, dataIndex: currentItem3Index }
    }
    if (i.dataType === 'item4') {
      currentItem4Index = currentItem3Index + '.' + item4Index++
      lastIndex = currentItem4Index
      return { ...i, dataIndex: currentItem4Index }
    }

    return i
  })
}

/** 为引言页中的节点添加 dataIndex
 * prefix: 附录的顺序编号，如0
 */
function getIntroductionBlockList(arr) {
  let item1Index = 1
  return arr.map((i) => (i.dataType === 'item1' ? { ...i, blockIndex: '0.' + item1Index++ } : i))
}

/** 为附录中的节点添加 dataIndex
 * prefix: 附录的顺序编号，如A, B...
 * arr: 附录的内容，对其中的 item1 - item2 添加dataIndex
 */
function getSortedAnnexBlockList(prefix = 'A.', arr) {
  let item1Index = 1,
    item2Index = 1,
    item3Index = 1,
    currentItem1Index = '',
    currentItem2Index = '',
    currentItem3Index = ''
  return arr.map((i) => {
    if (i.dataType === 'item1') {
      ;(item2Index = 1), (item3Index = 1)
      currentItem1Index = item1Index++
      return { ...i, blockIndex: prefix + currentItem1Index }
    }
    if (i.dataType === 'item2') {
      item3Index = 1
      currentItem2Index = currentItem1Index + '.' + item2Index++
      return { ...i, blockIndex: prefix + currentItem2Index }
    }
    if (i.dataType === 'item3') {
      currentItem3Index = currentItem2Index + '.' + item3Index++
      return { ...i, blockIndex: prefix + currentItem3Index }
    }

    return i
  })
}

/**
 * 将数组类型的节点数据转为页面数组
 * 此处数据会产生【章】级别嵌套
 */
export function getGroupedBlockList(blockList) {
  return blockList.reduce((list, item) => {
    // 含空白页
    if (allContentTypes.includes(item.dataType)) {
      list.push([item])
    } else {
      list[list.length - 1].push(item)
    }
    return list
  }, [])
}
/** 同上，用于结构树目录 */
export function getOutlineBlockList(blockList) {
  return blockList.reduce((list, item) => {
    // 不含空白页
    if (contentTypes.includes(item.dataType)) {
      list.push([item])
    } else {
      if (/item[1-4]/g.test(item.dataType)) {
        list[list.length - 1].push(item)
      }
    }
    return list
  }, [])
}

/**
 * 获取左侧导航树的数据
 * 在原来数组基础上增加 content 和 children 字段
 * 对【条】级别的数据进一步嵌套
 * */
function getTreeBlockList(arr) {
  return arr.map((blockList) => {
    const [chapterBlock, ...list] = blockList
    const itemArr = []
    if (list?.length) {
      let lastItem1 = null
      let lastItem2 = null
      let lastItem3 = null
      for (const item of list) {
        const newItem = {
          ...item,
          dataId: item.textData.dataId,
          children: []
        }
        if (item.dataType === 'item1') {
          lastItem1 = newItem
          itemArr.push(lastItem1)
        } else if (item.dataType === 'item2') {
          lastItem2 = newItem
          lastItem1.children.push(lastItem2)
        } else if (item.dataType === 'item3') {
          lastItem3 = newItem
          lastItem2.children.push(lastItem3)
        } else if (item.dataType === 'item4') {
          lastItem3.children.push(newItem)
        }
      }
    }
    return {
      ...chapterBlock,
      dataId: chapterBlock?.textData?.dataId,
      pageId: getPageByBlockId(chapterBlock?.blockId)?.dataset?.pageId,
      children: itemArr
    }
  })
}

/** 正文页面解析出的内容数据 */
export function getContentPageBlockList(tosave = false) {
  const doc = tinymce.activeEditor.getDoc()
  const pageNodes = [...doc.querySelectorAll('#tinymce>.page-wrapper [data-page-type="content"]')]
  return pageNodes.reduce((prev, node) => [...prev, ...parsePageData(node, tosave)], [])
}

// 工具函数,用于处理文档中标题的级别,可能存在跨级别情况,如 item1后直接是item3
// 导致这种情况包括:1.chapter插件取消中间层级的设置;2.删除中间层级标题内容
export function rectifyItemLevel(arr) {
  // 2. 对每块进行处理
  // ** 该方法直接修改数据内容,不建议使用这种处理 **
  function fn(list) {
    // 过滤出标题行 dataType=item1 ~ item4
    const itemBlockArr = list.filter((i) => /item[1-4]/g.test(i.dataType))
    let x = 0
    for (const item of itemBlockArr) {
      // 取出每项的数字,标题等级
      const i = Number(item.dataType[4])
      // 如果等级超过上一级别两个等级,如 item1, item3则降级处理
      if (i - x > 1) {
        x = x + 1
      } else {
        // 如果相同,或者只相差一个级别,或者更小则更新
        x = i
      }
      item.dataType = 'item' + x
    }
  }

  // 1. 分块
  const groupArr = []
  arr.forEach((item) => {
    if (contentTypes.includes(item.dataType)) {
      groupArr.push([item])
    } else {
      try {
        groupArr[groupArr.length - 1]?.push(item)
      } catch (error) {
        console.warn('---解析大纲结构出错---')
      }
    }
  })

  // 3
  groupArr.forEach(fn)
}

export function getContentData() {
  // 0,1,2
  const blockList = getContentPageBlockList()
  rectifyItemLevel(blockList)
  // 3. 为节点添加 dataIndex
  const list = getSortedBlockList(blockList)
  // 4. 将数组类型的节点数据转为页面数组，产生【章】级别嵌套
  const groups = getOutlineBlockList(list)
  // 5. 增加 content 和 children 字段，对【条】级别的数据进一步嵌套
  return getTreeBlockList(groups)
}
/** 获得 content 页面前后页面的内容 */
const getSiblingPageSheets = (type = 'head') => {
  return tinymce.activeEditor.dom.select('#tinymce>.page-wrapper .page-sheet').filter((node) => {
    if (type === 'head') {
      return headTypes.some((t) => node.dataset.pageType === t)
    }
    return tailTypes.some((t) => node.dataset.pageType === t) || node.dataset.pageType === 'annex'
  })
}

export const getStrData2Save = () => {
  const blockList = getContentPageBlockList(true)
  rectifyItemLevel(blockList)
  // 如果是结构化块 block 或个人收藏 collect 页面进入，只有单页的内容
  if (store.getters.editContentType === 'block' || store.getters.editContentType === 'collect') {
    const groupId = uuid()
    const data = blockList.map((i) => {
      if (!i.blockType) {
        i.setBlockType(store.getters.editContentType)
      }
      if (!i.groupId) {
        i.setGroupId(groupId)
      }
      return i
    })
    console.debug('---content page data---', data)
    return JSON.stringify(data)
  }

  // 如果是模板 template 或文档 document 页面进入，则正文前后的页面单独处理，最后拼到一起
  const headPageBlockList = getSiblingPageBlockList('head', true)
  const tailPageBlockList = getSiblingPageBlockList('tail', true)
  const groupedBlockList = getGroupedBlockList(blockList)
  const contentPageBlockList = groupedBlockList.map((i) => {
    const page = getPageByBlockId(i?.[0]?.blockId)
    const { pageId, layout: pageLayout } = page?.dataset || {}
    return new StdPage({ pageId, pageLayout, pageType: 'content', blockList: i })
  })
  // 文档的中英文类型透传
  const pageList = [...headPageBlockList, ...contentPageBlockList, ...tailPageBlockList]
  let pageNo = 1
  pageList.forEach((item) => {
    if (!['cover', 'signature', 'revision'].includes(item.pageType)) {
      item.pageNo = pageNo++
    }
  })
  const docData = new StdDoc({
    pageList,
    languageType: store.getters.languageType
  })
  console.debug('---all pages data---index', docData)
  return JSON.stringify(docData)
}

/** 数据用于接口保存 */
export function getSiblingPageBlockList(type, tosave = false) {
  return getSiblingPageSheets(type).map((node) => {
    const { pageType, pageId, annexType, layout = 'portrait' } = node.dataset
    const blockList = parsePageData(node, tosave)
    rectifyItemLevel(blockList)
    // 如果是引言页
    if (pageType === 'introduction') {
      return new StdPage({ pageId, pageType, blockList: getIntroductionBlockList(blockList) })
    }
    // 如果是附录
    if (isAnnexByType(pageType)) {
      const annexNo = node.querySelector('[data-annex-number]')?.dataset?.annexNumber
      const sortedBlockList = getSortedAnnexBlockList(annexNo + '.', blockList)
      const arr = [...new StdAnnexV2(node).data, ...sortedBlockList]
      return new StdPage({ pageId, pageType: annexType, pageLayout: layout, blockList: arr })
    }
    return new StdPage({ pageId, pageType, blockList })
  })
}

/**
 * 解析文本部分中的元素
 * @param {*} node 当前节点
 * @param {*} res 解析出来的元素应放置的集合
 */
export function getContentDatas(node, res) {
  if (!node) return
  let data = {}
  const nodeType = node.attributes?.map?.['data-type']
  if (node.type === 3) {
    // 纯文本节点
    data.content = node.value
    data.contentType = 'text'
  } else if (nodeType === 'footnote') {
    data.content = node.attributes?.map?.['data-note']
    data.contentType = nodeType
    data.contentNumber = node.attributes?.map?.['data-number']
  } else {
    //sup, sub
    ;(data.content = node.firstChild.value), (data.contentType = nodeType || 'text')
  }
  res.push(data)

  if (node.next) {
    getContentDatas(node.next, res)
  }
}

export function generateSiblingPage(pageType) {
  return new StdPage({ pageId: uuid(), pageType })
}

export function generateContentPage(dataType, pageLayout) {
  const isChpt = dataType === 'chapter'
  const { label, labelEn } = contentPrototypes.find((i) => i.dataType === dataType)
  const fullContent = store.getters.languageType === 'both' ? `${label}(${labelEn})` : label
  return new StdPage({
    pageId: uuid(),
    pageType: 'content',
    pageLayout,
    blockList: [
      {
        dataType,
        textData: {
          dataId: uuid(),
          contentList: [
            {
              fullContent: isChpt ? '' : fullContent,
              content: isChpt ? '' : label,
              contentEn: isChpt ? '' : labelEn
            }
          ]
        }
      }
    ]
  })
}

export function generateAnnexPage(pageType, index = 0) {
  const contentNumber = String.fromCharCode(65 + index)
  return new StdPage({
    pageId: uuid(),
    pageType,
    blockList: [
      {
        dataType: 'annex_number',
        textData: {
          dataId: uuid(),
          contentList: [
            {
              contentType: 'text',
              contentNumber,
              content: '附录',
              fullContent: '附录' + contentNumber
            }
          ]
        }
      },
      {
        dataType: 'annex_type_name',
        textData: {
          dataId: '',
          contentList: [
            {
              contentType: 'text',
              contentNumber: undefined,
              content: pageType,
              fullContent: '(' + (pageType === 'normativeAnnex' ? '规范性附录' : '资料性附录') + ')'
            }
          ]
        }
      },
      {
        dataType: 'annex_title',
        textData: {
          dataId: '',
          contentList: [
            {
              contentType: 'text',
              contentNumber: undefined,
              content: '未命名',
              fullContent: '未命名'
            }
          ]
        }
      }
    ]
  })
}
